#include <slm/vec3.h>

SLMATH_BEGIN()

void vec3::normalize()
{
	float len = length();
	SLMATH_VEC_ASSERT( len >= FLT_MIN );
	*this *= 1.f / len;
}

vec3 vec3::slerp(const vec3& from, const vec3& to, float delta)
{
	return vec3(
		from.x + delta * (to.x - from.x),
		from.y + delta * (to.y - from.y),
		from.z + delta * (to.z - from.z)
		);
}

vec3 vec3::facenormal_ccw( const vec3& v0, const vec3& v1, const vec3& v2 )
{
	vec3 a( v1.x-v0.x, v1.y-v0.y, v1.z-v0.z );
	vec3 b( v2.x-v0.x, v2.y-v0.y, v2.z-v0.z );
	vec3 res( a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x );
	res *= 1.f/res.length();
	return res;
}

vec3 vec3::facenormal_cw( const vec3& v0, const vec3& v1, const vec3& v2 )
{
	return vec3::facenormal_ccw( v0, v2, v1 );
}

vec3 vec3::faceforward( const vec3& n, const vec3& i, const vec3& nref )
{
	return nref.dot(i) < 0.f ? n : -n;
}

vec3 vec3::reflect(const vec3& n )const
{
	return *this - n*( 2.f* n.dot(*this) );
}

vec3 vec3::refract(const vec3& n, float eta )const
{
	float ndoti = n.dot(*this);
	float k = 1.0f - eta*eta*(1.0f - ndoti*ndoti);
	if ( k < 0.f )
		return vec3(0.f);
	else
		return *this*eta - n*(eta*ndoti+sqrtf(k));
}

bool equal(const vec3& left, const vec3& right, float tolerance)
{
	return slm::equal(left.x, right.x, tolerance) &&
		slm::equal(left.y, right.y, tolerance) && 
		slm::equal(left.z, right.z, tolerance);
}

SLMATH_END()

// This file is part of 'slm' C++ library. Copyright (C) 2009 Jani Kajala (kajala@gmail.com). See http://sourceforge.net/projects/slm/
